﻿

//链接：https://ac.nowcoder.com/acm/problem/222104
//来源：牛客网
//小红拿到了一个只由小写字母组成的字符串。她准备把这个字符串重排（只改变字母的顺序，不改变数量）
//重排后小红想让新字符串不包含任意两个相同的相邻字母。
//你能帮帮她吗？
//输入描述 :
//第一行一个正整数
//    第二行为一个长度为
//    �
//    n 的、只由小写字母组成的字符串。
//    输出描述 :
//如果可以完成重排，请在第一行输出一个“yes”，第二行输出重排后的字符串。如果有多个正解，输出任意即可。
//如果不能重排，则直接输出“no”
//示例1
//输入
//复制
//5
//aaaaa
//输出
//复制
//no
//示例2
//输入
//复制
//7
//aabbccc
//输出
//复制
//yes
//cabcabc
//说明
//bcbcaca也是正确答案（正确答案还有很多，输出任意即可）



//方法：确定什么时候会一定重复，然后根据间隔排布让它不会重复

//思路：我们可以得到一个规律如果最大的字母个数大于总个数的1/2，那么他肯定会有重复，否则就是无，
//然后进行排列就好，
//排列方法：我们先把最长的按照间一个排一个，那么它一定中间有空格，可能末尾剩下的也有空格，（也就是我们
//的偶数下标排列，每次我们都按照某个字母的个数去排布，这样就不会有重复了；也许会问？最后不是有剩余的连着
//的区域吗，为什么不会重复？这里因为最长的字母已经排完了，它不可能从偶数下标末端，一直到奇数下标也
//到那个位置）
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
    int n;
    cin >> n;
    string s;
    cin >> s;
    int mxcount = 0;
    int mxindex = 0;
    vector<char> v(n);
    string ret;
    int hash[26] = { 0 };
    //获得出现次数最多的字母：
    for (int i = 0; i < n; i++) {
        if (mxcount < ++hash[s[i] - 'a']) {
            mxcount = hash[s[i] - 'a'];
            mxindex = s[i];
        }
    }
    //根据出现最多的字母个数判断是否重排后会重复：
    if (mxcount > (n + 1) / 2)cout << "no" << endl;

    else {

        cout << "yes" << endl;
        //输出yes就进行重排：
        int i = 0;
        while (mxcount--) {
            v[i] = mxindex;//把最多的先按照隔一个放一个的方式进行排布
            i += 2;
        }
        //这里i的开头，我们是接着上次排maxalpha后面接着隔一个放一个，保证偶数下标都放完，接下来就是
        //奇数下标，然后一次跳跃插入即可
        for (int j = 0; j < 26; j++) {

            if (hash[j] > 0 && j + 'a' != mxindex) {
                while (hash[j]--) {
                    if (i >= n) i = 1;//这里当偶数次下标插入完毕会发生越界下面转化奇数下标继续
                    v[i] = j + 'a';
                    i += 2;
                }
            }

        }
        for (auto a : v)ret += a;

        cout << ret << endl;
    }
    return 0;
}